﻿using Mes.Application.DTO.Inputs.Operations;
using Mes.Application.DTO.Results.Operations;
using Mes.Domain.BoundedContext;
using AutoMapper;
using Mes.Domain.BoundedContext.Entities.Operations;
using Microsoft.EntityFrameworkCore;
using Mes.Infrastructure.Data.BoundedContext.Extensions;
using Mes.Infrastructure.Data.BoundedContext.RepositoryBase;
using Mes.Application.Common;
using Mes.Application.Common.Resource;
using Mes.Infrastructure.Data.BoundedContext.Repositories.MasterData;

namespace Mes.Application.Services.Operations
{
    public class StdOperService : IStdOperService
    {
        private readonly INoIdRepository<StdOper> _stdOperRepository;
        private readonly IMapper _mapper;
        private readonly INoIdRepository<StdOperAttr> _stdOperAttrRepository;
        private readonly INoIdRepository<Attr> _attrRepository;
        private readonly INoIdRepository<StdOperEntLink> _stdOperEntLinkRepository;
        private readonly IProductionUnitRepository _productionUnitRepository;
        private readonly INoIdRepository<StdOperStepGrp> _stdOperStepGrpRepository;
        private readonly INoIdRepository<StdOperStep> _stdOperStepRepository;
        public StdOperService(INoIdRepository<StdOper> stdOperRepository,
            IMapper mapper,
            INoIdRepository<StdOperAttr> stdOperAttrRepository,
            INoIdRepository<Attr> attrRepository,
            INoIdRepository<StdOperEntLink> stdOperEntLinkRepository,
            IProductionUnitRepository productionUnitRepository,
            INoIdRepository<StdOperStepGrp> stdOperStepGrpRepository,
            INoIdRepository<StdOperStep> stdOperStepRepository)
        {
            if (stdOperRepository == null || mapper == null || stdOperAttrRepository == null || attrRepository == null || stdOperEntLinkRepository == null
                || productionUnitRepository == null || stdOperStepGrpRepository == null || stdOperStepRepository == null)
            {
                throw new ArgumentNullException();
            }
            _stdOperRepository = stdOperRepository; //注入仓储类
            _mapper = mapper;
            _stdOperAttrRepository = stdOperAttrRepository;
            _attrRepository = attrRepository;
            _stdOperEntLinkRepository = stdOperEntLinkRepository;
            _productionUnitRepository = productionUnitRepository;
            _stdOperStepGrpRepository = stdOperStepGrpRepository;
            _stdOperStepRepository = stdOperStepRepository;
        }

        /// <summary>
        /// 添加标准工序
        /// </summary>
        /// <param name="stdOperInput"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task AddStandardOperationAsync(StdOperInput stdOperInput)
        {
            if (stdOperInput.StdOperEntLinks.Count == 0)
            {
                throw new CustomException(Messages.StdOperNotBindingEntity);
            }

            if (_stdOperRepository.Exists(x => x.Oper_Id == stdOperInput.Oper_Id))
            {
                throw new CustomException(Messages.StdOperAlreadyExist);
            }

            Dictionary<int, int> entIds = new Dictionary<int, int>();
            var stdOperEntLinks = new HashSet<StdOperEntLink>();
            foreach (var item in stdOperInput.StdOperEntLinks)
            {
                if (!_productionUnitRepository.Exists(x => x.Id == item.Ent_Id))
                {
                    throw new CustomException(Messages.EntityNotFound);
                }

                if (entIds.ContainsKey(item.Ent_Id))
                {
                    throw new CustomException(Messages.EntityDuplication);
                }
                else
                {
                    entIds[item.Ent_Id] = 1;
                }

                var stdOperEntLink = _mapper.Map<StdOperEntLink>(item);
                stdOperEntLink.Oper_Id = stdOperInput.Oper_Id;
                stdOperEntLinks.Add(stdOperEntLink);
            }
            await _stdOperEntLinkRepository.AddRangeAsync(stdOperEntLinks);

            if (stdOperInput.StdOperAttrs.Count > 0)
            {
                Dictionary<int, int> attrIds = new Dictionary<int, int>();
                var stdOperAttrs = new HashSet<StdOperAttr>();
                foreach (var item in stdOperInput.StdOperAttrs)
                {
                    if (!_attrRepository.Exists(x => x.Attr_Id == item.Attr_Id))
                    {
                        throw new CustomException(Messages.AttrNotFound);
                    }

                    if (attrIds.ContainsKey(item.Attr_Id))
                    {
                        throw new CustomException(Messages.AttrDuplication);
                    }
                    else
                    {
                        attrIds[item.Attr_Id] = 1;
                    }

                    var stdOperAttr = _mapper.Map<StdOperAttr>(item);
                    stdOperAttr.Oper_Id = stdOperInput.Oper_Id;
                    stdOperAttrs.Add(stdOperAttr);
                }
                await _stdOperAttrRepository.AddRangeAsync(stdOperAttrs);
            }

            if (stdOperInput.StdOperStepGrps.Count > 0)
            {
                Dictionary<int, int> stepGrpIds = new Dictionary<int, int>();
                var stdOperStepGrps = new HashSet<StdOperStepGrp>();
                foreach (var item in stdOperInput.StdOperStepGrps)
                {
                    if (_stdOperStepGrpRepository.Exists(x => x.Oper_Id == stdOperInput.Oper_Id && x.Step_Grp_Id == item.Step_Grp_Id))
                    {
                        throw new CustomException(Messages.StepGroupAlreadyExist);
                    }

                    if (stepGrpIds.ContainsKey(item.Step_Grp_Id))
                    {
                        throw new CustomException(Messages.StepGroupDuplication);
                    }
                    else
                    {
                        stepGrpIds[item.Step_Grp_Id] = 1;
                    }

                    var stdOperStepGrp = _mapper.Map<StdOperStepGrp>(item);
                    stdOperStepGrp.Oper_Id = stdOperInput.Oper_Id;
                    stdOperStepGrps.Add(stdOperStepGrp);
                }
                await _stdOperStepGrpRepository.AddRangeAsync(stdOperStepGrps);
            }

            foreach (var stepGroup in stdOperInput.StdOperStepGrps)
            {
                if (stepGroup.StdOperSteps.Count > 0)
                {
                    Dictionary<int, int> stepIds = new Dictionary<int, int>();
                    var stdOperSteps = new HashSet<StdOperStep>();
                    foreach (var item in stepGroup.StdOperSteps)
                    {
                        if (_stdOperStepRepository.Exists(x => x.Oper_Id == stdOperInput.Oper_Id && x.Step_No == item.Step_No))
                        {
                            throw new CustomException(Messages.StepAlreadyExist);
                        }

                        if (stepIds.ContainsKey(item.Step_No))
                        {
                            throw new CustomException(Messages.StepDuplication);
                        }
                        else
                        {
                            stepIds[item.Step_No] = 1;
                        }

                        var stdOperStep = _mapper.Map<StdOperStep>(item);
                        stdOperStep.Oper_Id = stdOperInput.Oper_Id;
                        stdOperStep.Step_Grp_Id = stepGroup.Step_Grp_Id;
                        stdOperSteps.Add(stdOperStep);
                    }
                    await _stdOperStepRepository.AddRangeAsync(stdOperSteps);
                }
            }

            var stdOper = _mapper.Map<StdOper>(stdOperInput);
            await _stdOperRepository.AddAsync(stdOper);
            int status = await _stdOperRepository.SaveAsync();
            if (status <= 0)
            {
                throw new CustomException(Messages.SavingFailure);
            }
        }

        /// <summary>
        /// 编辑标准工序
        /// </summary>
        /// <param name="stdOperUpdateInput"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task UpdateStandardOperationAsync(StdOperUpdateInput stdOperUpdateInput)
        {
            if (stdOperUpdateInput.StdOperEntLinks.Count == 0)
            {
                throw new CustomException(Messages.StdOperNotBindingEntity);
            }

            var stdOper = _stdOperRepository.Find(x => x.Oper_Id == stdOperUpdateInput.Oper_Id);
            if (stdOper == null)
            {
                throw new CustomException(Messages.StdOperNotFound);
            }

            var oldStdOperEntLinks = _stdOperEntLinkRepository.Query().Where(x => x.Oper_Id == stdOperUpdateInput.Oper_Id).ToListAsync();
            if (oldStdOperEntLinks.Result.Count > 0)
            {
                foreach (var item in oldStdOperEntLinks.Result)
                {
                    if (stdOperUpdateInput.StdOperEntLinks.Count > 0)
                    {
                        var result = stdOperUpdateInput.StdOperEntLinks.Where(x => x.Ent_Id == item.Ent_Id).ToList();
                        if (result.Count > 1)
                        {
                            throw new CustomException(Messages.EntityDuplication);
                        }
                        else if (result.Count == 0)
                        {
                            await _stdOperEntLinkRepository.DeleteAsync(x => x.Oper_Id == item.Oper_Id && x.Ent_Id == item.Ent_Id);
                        }
                    }
                    else
                    {
                        await _stdOperEntLinkRepository.DeleteAsync(x => x.Oper_Id == item.Oper_Id);
                        break;
                    }
                }
            }

            Dictionary<int, int> entIds = new Dictionary<int, int>();
            var stdOperEntLinks = new HashSet<StdOperEntLink>();
            foreach (var item in stdOperUpdateInput.StdOperEntLinks)
            {
                if (!_productionUnitRepository.Exists(x => x.Id == item.Ent_Id))
                {
                    throw new CustomException(Messages.EntityNotFound);
                }

                if (entIds.ContainsKey(item.Ent_Id))
                {
                    throw new CustomException(Messages.EntityDuplication);
                }
                else
                {
                    entIds[item.Ent_Id] = 1;
                }

                var stdOperEntLink = _stdOperEntLinkRepository.Find(x => (x.Oper_Id == stdOperUpdateInput.Oper_Id && x.Ent_Id == item.Ent_Id));
                if (stdOperEntLink == null)
                {
                    stdOperEntLink = _mapper.Map<StdOperEntLink>(item);
                    stdOperEntLink.Oper_Id = stdOperUpdateInput.Oper_Id;
                    stdOperEntLinks.Add(stdOperEntLink);
                }
                else
                {
                    stdOperEntLink.Est_Prod_Rate = item.Est_Prod_Rate;
                    stdOperEntLink.Est_Lab_Rate = item?.Est_Lab_Rate;
                    stdOperEntLink.Est_Setup_Time = item?.Est_Setup_Time;
                    stdOperEntLink.Est_Teardown_Time = item?.Est_Teardown_Time;
                    stdOperEntLink.Est_Transfer_Time = item?.Est_Transfer_Time;
                    _stdOperEntLinkRepository.Update(stdOperEntLink);
                }
            }
            if (stdOperEntLinks.Count > 0)
            {
                await _stdOperEntLinkRepository.AddRangeAsync(stdOperEntLinks);
            }
            
            var oldStdOperAttrs = _stdOperAttrRepository.Query().Where(x => x.Oper_Id == stdOperUpdateInput.Oper_Id).ToListAsync();
            if (oldStdOperAttrs.Result.Count > 0)
            {
                foreach (var item in oldStdOperAttrs.Result)
                {
                    if (stdOperUpdateInput.StdOperAttrs.Count > 0)
                    {
                        var result = stdOperUpdateInput.StdOperAttrs.Where(x => x.Attr_Id == item.Attr_Id).ToList();
                        if (result.Count > 1)
                        {
                            throw new CustomException(Messages.AttrDuplication);
                        }
                        else if (result.Count == 0)
                        {
                            await _stdOperAttrRepository.DeleteAsync(x => x.Oper_Id == item.Oper_Id && x.Attr_Id == item.Attr_Id);
                        }
                    }
                    else
                    {
                        await _stdOperAttrRepository.DeleteAsync(x => x.Oper_Id == item.Oper_Id);
                        break;
                    }
                }
            }

            if (stdOperUpdateInput.StdOperAttrs.Count > 0)
            {
                Dictionary<int, int> attrIds = new Dictionary<int, int>();
                var stdOperAttrs = new HashSet<StdOperAttr>();
                foreach (var item in stdOperUpdateInput.StdOperAttrs)
                {
                    if (attrIds.ContainsKey(item.Attr_Id))
                    {
                        throw new CustomException(Messages.AttrDuplication);
                    }
                    else
                    {
                        attrIds[item.Attr_Id] = 1;
                    }

                    if (!_attrRepository.Exists(x => x.Attr_Id == item.Attr_Id))
                    {
                        throw new CustomException(Messages.AttrNotFound);
                    }

                    var stdOperAttr = _stdOperAttrRepository.Find(x => (x.Oper_Id == stdOperUpdateInput.Oper_Id && x.Attr_Id == item.Attr_Id));
                    if (stdOperAttr == null)
                    {
                        stdOperAttr = _mapper.Map<StdOperAttr>(item);
                        stdOperAttr.Oper_Id = stdOperUpdateInput.Oper_Id;
                        stdOperAttrs.Add(stdOperAttr);
                    }
                    else
                    {
                        stdOperAttr.Attr_Value = item.Attr_Value;
                        stdOperAttr.Notes = item.Notes;
                        stdOperAttr.Last_Edit_Comment = item?.Last_Edit_Comment;
                        _stdOperAttrRepository.Update(stdOperAttr);
                    }
                }
                if (stdOperAttrs.Count > 0)
                {
                    await _stdOperAttrRepository.AddRangeAsync(stdOperAttrs);
                }
            }

            var oldStdOperStepGrps = _stdOperStepGrpRepository.Query().Where(x => x.Oper_Id == stdOperUpdateInput.Oper_Id).ToListAsync();
            if (oldStdOperStepGrps.Result.Count > 0)
            {
                foreach (var item in oldStdOperStepGrps.Result)
                {
                    if (stdOperUpdateInput.StdOperStepGrps.Count > 0)
                    {
                        var result = stdOperUpdateInput.StdOperStepGrps.Where(x => x.Step_Grp_Id == item.Step_Grp_Id).ToList();
                        if (result.Count > 1)
                        {
                            throw new CustomException(Messages.StepGroupDuplication);
                        }
                        else if (result.Count == 0) // 若更新的工步组的id不在工步组表中，则将工步组表中的工步组删除，同时删除工步表中此工步组的工步
                        {
                            await _stdOperStepGrpRepository.DeleteAsync(x => x.Oper_Id == item.Oper_Id && x.Step_Grp_Id == item.Step_Grp_Id);
                            await _stdOperStepRepository.DeleteAsync(x => x.Oper_Id == item.Oper_Id && x.Step_Grp_Id == item.Step_Grp_Id);
                        }
                        else
                        {
                            var oldStdOperSteps = _stdOperStepRepository.Query().Where(x => x.Oper_Id == stdOperUpdateInput.Oper_Id && x.Step_Grp_Id == item.Step_Grp_Id).ToListAsync();
                            if (oldStdOperSteps.Result.Count > 0) // 更新前工步表中含有此工步组的工步
                            {
                                foreach (var element in result) // 更新的工步组的id可以在工步组表中找到
                                {
                                    if (element.StdOperSteps.Count > 0) // 更新的工步组中含工步
                                    {
                                        foreach (var e in oldStdOperSteps.Result)
                                        {
                                            var step = element.StdOperSteps.Where(x => x.Step_No == e.Step_No).ToList();
                                            if (step.Count == 0) // 删除表中存在但更新的工序输入中不存在的工步
                                            {
                                                await _stdOperStepRepository.DeleteAsync(x => x.Oper_Id == item.Oper_Id && x.Step_Grp_Id == item.Step_Grp_Id && x.Step_No == e.Step_No);
                                            }
                                        }
                                    }
                                    else // 更新的工步组中不含工步，则需删除工步表中此工步组所含的工步
                                    {
                                        await _stdOperStepRepository.DeleteAsync(x => x.Oper_Id == item.Oper_Id && x.Step_Grp_Id == item.Step_Grp_Id);
                                    }
                                }
                            }
                        }
                    }
                    else // 若更新中不含任何工步组，则删除此工序的所有工步组和工步
                    {
                        await _stdOperStepGrpRepository.DeleteAsync(x => x.Oper_Id == item.Oper_Id);
                        await _stdOperStepRepository.DeleteAsync(x => x.Oper_Id == item.Oper_Id);
                        break;
                    }
                }
            }

            if (stdOperUpdateInput.StdOperStepGrps.Count > 0)
            {
                Dictionary<int, int> stepGrpIds = new Dictionary<int, int>();
                var stdOperStepGrps = new HashSet<StdOperStepGrp>();
                foreach (var item in stdOperUpdateInput.StdOperStepGrps)
                {
                    if (stepGrpIds.ContainsKey(item.Step_Grp_Id))
                    {
                        throw new CustomException(Messages.StepGroupDuplication);
                    }
                    else
                    {
                        stepGrpIds[item.Step_Grp_Id] = 1;
                    }

                    Dictionary<int, int> stepIds = new Dictionary<int, int>();
                    var stdOperSteps = new HashSet<StdOperStep>();
                    var stdOperStepGrp = _stdOperStepGrpRepository.Find(x => (x.Oper_Id == stdOperUpdateInput.Oper_Id && x.Step_Grp_Id == item.Step_Grp_Id));
                    if (stdOperStepGrp == null) // 若输入的工步组不存在则新增工步组和工步
                    {
                        stdOperStepGrp = _mapper.Map<StdOperStepGrp>(item);
                        stdOperStepGrp.Oper_Id = stdOperUpdateInput.Oper_Id;
                        stdOperStepGrps.Add(stdOperStepGrp);
                        foreach (var element in item.StdOperSteps)
                        {
                            if (stepIds.ContainsKey(element.Step_No))
                            {
                                throw new CustomException(Messages.StepDuplication);
                            }
                            else
                            {
                                stepIds[element.Step_No] = 1;
                            }

                            var stdOperStep = _mapper.Map<StdOperStep>(element);
                            stdOperStep.Oper_Id = stdOperUpdateInput.Oper_Id;
                            stdOperStep.Step_Grp_Id = item.Step_Grp_Id;
                            stdOperSteps.Add(stdOperStep);
                        }
                    }
                    else
                    {
                        stdOperStepGrp.Step_Grp_Desc = item.Step_Grp_Desc; // 若输入的工步组存在则更新工步组
                        stdOperStepGrp.Step_Grp_Seq = item.Step_Grp_Seq;
                        stdOperStepGrp.Last_Edit_Comment = item?.Last_Edit_Comment;
                        _stdOperStepGrpRepository.Update(stdOperStepGrp);
                        foreach (var element in item.StdOperSteps)
                        {
                            if (stepIds.ContainsKey(element.Step_No))
                            {
                                throw new CustomException(Messages.StepDuplication);
                            }
                            else
                            {
                                stepIds[element.Step_No] = 1;
                            }

                            var stdOperStep = _stdOperStepRepository.Find(x => x.Oper_Id == stdOperUpdateInput.Oper_Id && x.Step_Grp_Id == item.Step_Grp_Id && x.Step_No == element.Step_No);
                            if (stdOperStep == null) // 若输入的工步组存在但其下的工步不存在，则新增工步
                            {
                                stdOperStep = _mapper.Map<StdOperStep>(element);
                                stdOperStep.Oper_Id = stdOperUpdateInput.Oper_Id;
                                stdOperStep.Step_Grp_Id = item.Step_Grp_Id;
                                stdOperSteps.Add(stdOperStep);
                            }
                            else // 若输入的工步组存在且其下的工步也存在，则更新工步
                            {
                                stdOperStep.Step_Seq = element.Step_Seq;
                                stdOperStep.Step_Name = element?.Step_Name;
                                stdOperStep.Step_Desc = element.Step_Desc;
                                stdOperStep.Last_Edit_Comment = element?.Last_Edit_Comment;
                                _stdOperStepRepository.Update(stdOperStep);
                            }
                        }
                    }
                    if (stdOperSteps.Count > 0)
                    {
                        await _stdOperStepRepository.AddRangeAsync(stdOperSteps);
                    }
                }
                if (stdOperStepGrps.Count > 0)
                {
                    await _stdOperStepGrpRepository.AddRangeAsync(stdOperStepGrps);
                }
            }

            stdOper.Last_Edit_At = DateTime.Now;
            stdOper.Oper_Desc = stdOperUpdateInput.Oper_Desc;
            stdOper.Oper_Type = stdOperUpdateInput.Oper_Type;
            stdOper.Oper_Cost = stdOperUpdateInput.Oper_Cost;
            stdOper.Notes = stdOperUpdateInput.Notes;
            _stdOperRepository.Update(stdOper);
            int status = await _stdOperRepository.SaveAsync();
            if (status <= 0)
            {
                throw new CustomException(Messages.SavingFailure);
            }
        }

        /// <summary>
        /// 删除标准工序
        /// </summary>
        /// <param name="oper_ids"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task DeleteStandardOperationAsync(string[] oper_ids)
        {
            await _stdOperEntLinkRepository.DeleteAsync(x => oper_ids.Contains(x.Oper_Id));
            await _stdOperAttrRepository.DeleteAsync(x => oper_ids.Contains(x.Oper_Id));
            await _stdOperStepGrpRepository.DeleteAsync(x => oper_ids.Contains(x.Oper_Id));
            await _stdOperStepRepository.DeleteAsync(x => oper_ids.Contains(x.Oper_Id));
            await _stdOperRepository.DeleteAsync(x => oper_ids.Contains(x.Oper_Id));
            int status = await _stdOperRepository.SaveAsync();
            if (status <= 0)
            {
                throw new CustomException(Messages.SavingFailure);
            }
        }

        /// <summary>
        /// 查询指定标准工序
        /// </summary>
        /// <param name="oper_id"></param>
        /// <returns>StdOperResult</returns>
        /// <exception cref="CustomException"></exception>
        public async Task<StdOperResult> GetStandardOperationAsync(string oper_id)
        {
            var stdOper = await _stdOperRepository.Query().Where(x => x.Oper_Id == oper_id).FirstOrDefaultAsync();
            if (stdOper == null)
            {
                throw new CustomException(Messages.StdOperNotFound);
            }
            var data = _mapper.Map<StdOperResult>(stdOper);

            var stdOperEntLinks = await _stdOperEntLinkRepository.Query().Where(x => oper_id == x.Oper_Id).ToListAsync();
            if (stdOperEntLinks.Count > 0)
            {
                var stdOperEntLink = stdOperEntLinks.Where(x => x.Oper_Id == oper_id).ToList();
                data.StdOperEntLinks = _mapper.Map<List<StdOperEntLinkResult>>(stdOperEntLink);
                foreach (var element in data.StdOperEntLinks)
                {
                    var productionUnit = _productionUnitRepository.Find(x => x.Id == element.Ent_Id);
                    element.ProductionUnitCode = productionUnit.ProductionUnitCode;
                    element.ProductionUnitName = productionUnit.ProductionUnitName;
                }
            }

            var stdOperAttrs = await _stdOperAttrRepository.Query().Where(x => oper_id == x.Oper_Id).ToListAsync();
            if (stdOperAttrs.Count > 0)
            {
                var stdOperAttr = stdOperAttrs.Where(x => x.Oper_Id == oper_id).ToList();
                data.StdOperAttrs = _mapper.Map<List<StdOperAttrResult>>(stdOperAttr);
                foreach (var element in data.StdOperAttrs)
                {
                    var attr = _attrRepository.Find(x => x.Attr_Id == element.Attr_Id);
                    element.Attr_Desc = attr.Attr_Desc;
                    element.Data_Type = attr.Data_Type;
                }
            }

            var stdOperStepGrps = await _stdOperStepGrpRepository.Query().Where(x => oper_id == x.Oper_Id).ToListAsync();
            if (stdOperStepGrps.Count > 0)
            {
                var stdOperStepGrp = stdOperStepGrps.Where(x => x.Oper_Id == oper_id).ToList();
                data.StdOperStepGrps = _mapper.Map<List<StdOperStepGrpResult>>(stdOperStepGrp);
                foreach (var element in data.StdOperStepGrps)
                {
                    var stdOperStep = _stdOperStepRepository.Query().Where(x => x.Oper_Id == oper_id && x.Step_Grp_Id == element.Step_Grp_Id).ToList();
                    element.StdOperSteps = _mapper.Map<List<StdOperStepResult>>(stdOperStep);
                }
            }

            return data;
        }

        /// <summary>
        /// 分页查询标准工序
        /// </summary>
        /// <param name="stdOperPageInput"></param>
        /// <returns>PagedItemsData<StdOperResult></returns>
        /// <exception cref="CustomException"></exception>
        public async Task<PagedItemsData<StdOperResult>> GetStandardOperationsAsync(StdOperPageInput stdOperPageInput)
        {
            var stdOper = await _stdOperRepository.Query().Where(x => x.Oper_Id.Contains(stdOperPageInput.Oper_Id)).OrderBy(x => x.Oper_Id).ToPagedAsync(stdOperPageInput.PagedInput);
            if (stdOper == null)
            {
                throw new CustomException(Messages.StdOperNotFound);
            }
            var data = _mapper.Map<PagedItemsData<StdOperResult>>(stdOper);
            var stdOperIds = data.Items.Select(x => x.Oper_Id).ToList();
            if (stdOperIds.Count > 0)
            {
                var stdOperEntLinks = await _stdOperEntLinkRepository.Query().Where(x => stdOperIds.Contains(x.Oper_Id)).ToListAsync();
                if (stdOperEntLinks.Count > 0)
                {
                    foreach (var item in data.Items)
                    {
                        var stdOperEntLink = stdOperEntLinks.Where(x => x.Oper_Id == item.Oper_Id).ToList();
                        if (stdOperEntLink != null && stdOperEntLink.Count > 0)
                        {
                            item.StdOperEntLinks = _mapper.Map<List<StdOperEntLinkResult>>(stdOperEntLink);
                            foreach (var element in item.StdOperEntLinks)
                            {
                                var productionUnit = _productionUnitRepository.Find(x => x.Id == element.Ent_Id);
                                //if (productionUnit == null)
                                //{
                                //    throw new CustomException(Messages.EntityNotFound);
                                //}
                                element.ProductionUnitCode = productionUnit?.ProductionUnitCode??String.Empty;
                                element.ProductionUnitName = productionUnit?.ProductionUnitName ?? String.Empty;
                            }
                        }
                    }
                }

                var stdOperAttrs = await _stdOperAttrRepository.Query().Where(x => stdOperIds.Contains(x.Oper_Id)).ToListAsync();
                if (stdOperAttrs.Count > 0)
                {
                    foreach (var item in data.Items)
                    {
                        var stdOperAttr = stdOperAttrs.Where(x => x.Oper_Id == item.Oper_Id).ToList();
                        if (stdOperAttr != null && stdOperAttr.Count > 0)
                        {
                            item.StdOperAttrs = _mapper.Map<List<StdOperAttrResult>>(stdOperAttr);
                            foreach (var element in item.StdOperAttrs)
                            {
                                var attr = _attrRepository.Find(x => x.Attr_Id == element.Attr_Id);
                                if (attr == null)
                                {
                                    throw new CustomException(Messages.AttrNotFound);
                                }
                                element.Attr_Desc = attr.Attr_Desc;
                                element.Data_Type = attr.Data_Type;
                            }
                        }
                    }
                }

                var stdOperStepGrps = await _stdOperStepGrpRepository.Query().Where(x => stdOperIds.Contains(x.Oper_Id)).ToListAsync();
                if (stdOperStepGrps.Count > 0)
                {
                    foreach (var item in data.Items)
                    {
                        var stdOperStepGrp = stdOperStepGrps.Where(x => x.Oper_Id == item.Oper_Id).ToList();
                        if (stdOperStepGrp != null && stdOperStepGrp.Count > 0)
                        {
                            item.StdOperStepGrps = _mapper.Map<List<StdOperStepGrpResult>>(stdOperStepGrp);
                            foreach (var element in item.StdOperStepGrps)
                            {
                                var stdOperStep = _stdOperStepRepository.Query().Where(x => x.Oper_Id == item.Oper_Id && x.Step_Grp_Id == element.Step_Grp_Id).ToList();
                                if (stdOperStep != null && stdOperStep.Count > 0)
                                {
                                    element.StdOperSteps = _mapper.Map<List<StdOperStepResult>>(stdOperStep);
                                }
                            }
                        }
                    }
                }
            }

            return data;
        }
    }
}
